#pragma once
namespace JY_Link
{
	template <class T>
	class Unidirectional_Link
	{
	public:
		Unidirectional_Link()
		{
			head = nullptr;
			tail = nullptr;
		};
		~Unidirectional_Link()
		{
			if(head)
				Clean();
		};
		void Push(T* node)
		{
			if (head == nullptr)
			{
				head = node;
				tail = node;
				head->next = nullptr;
			}
			else
			{
				tail->next = node;
				tail = node;
				tail->next = nullptr;
			}
		};
		void Insert(T* node)
		{
			if (head == nullptr)
			{
				head = node;
				tail = node;
				tail->next = nullptr;
			}
			else
			{
				node->next = head;
				head = node;
			}
		};
		bool Clean()
		{
			T* p = head;
			while (p)
			{
				head = head->next;
				delete p;
				p = head;
			}
			tail = nullptr;
		};
		bool DelXNode(size_t x)
		{
			T* p = head;
			T* temp = nullptr;
			if (x == 0)
			{
				head = head->next;
				delete p;
			}
			else
			{
				int n = 1;
				while (p)
				{
					if (x == n)
					{
						temp = p->next;
						p->next = temp->next;
						break;
					}
					p = p->next;
					n++;
				}
			}
			if (temp)
			{
				delete temp;
				return true;
			}
			else
			{
				return false;
			}
		};
		T* GetXNode(size_t x)
		{
			T* p = head;
			T* temp = nullptr;
			int n = 0;
			while (p)
			{
				if (x == n)
				{
					temp = p;
					break;
				}
				p = p->next;
				n++;
			}
			return temp;
		};
		T* GetHead()
		{
			return head;
		};
		T* GetTail()
		{
			return tail;
		}
	private:
		T * head;
		T* tail;
	};
	
	template <class T>
	class Bidirectional_Link
	{
	public:
		Bidirectional_Link()
		{
			head = nullptr;
			tail = nullptr;
		};
		~Bidirectional_Link()
		{
			if (head)
				Clean();
		};
		void Push(T* node)
		{
			if (head == nullptr)
			{
				head = node;
				tail = node;
				head->next = nullptr;
				head->front = nullptr;
			}
			else
			{
				node->front = tail;
				node->next = nullptr;
				tail->next = node;
				tail = node;
			}
		};
		void Insert(T* node)
		{
			if (head == nullptr)
			{
				head = node;
				tail = node;
				head->next = nullptr;
				head->front = nullptr;
			}
			else
			{
				head->front = node;
				node->front = nullptr;
				node->next = head;
				head = node;
			}
		};
		bool Clean()
		{
			T* p = head;
			while (p)
			{
				head = head->next;
				delete p;
				p = head;
			}
			tail = nullptr;
		};

	private:
		T * head;
		T* tail;
	};

	template <class T>
	class Stack_Link
	{
	public:
		Stack_Link()
		{
			bottom = nullptr;
			top = nullptr;
		};
		~Stack_Link() {};
		void Push(T* node)
		{
			if (bottom == nullptr)
			{
				bottom = node;
				top = node;
				node->next = nullptr;
			}
			else
			{
				node->next = top;
				top = node;
			}
		};
		T* Pop()
		{
			if (top != nullptr)
			{
				T* temp = top;
				if (top == bottom)
				{
					top = nullptr;
					bottom = nullptr;
				}
				else
				{
					top = top->next;
				}
				temp->next = nullptr;
				return temp;
			}
			else
				return nullptr;
		};	
		T* GetTop()
		{
			if (top != nullptr)
			{
				return top;
			}
			else
				return nullptr;
		};
		bool IsEmpty()
		{
			if (bottom == nullptr)
				return true;
			return false;
		};
	private:
		T * bottom;
		T* top;
	};
}
